package com.ruoyi.quartz.controller;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
import com.ruoyi.quartz.util.CronUtils;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 调度任务信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/job")
public class SysJobController extends BaseController {
  @Autowired private ISysJobService jobService;

  /** 查询定时任务列表 */
  @PreAuthorize("@ss.hasPermi('monitor:job:list')")
  @GetMapping("/list")
  public TableDataInfo list(SysJob sysJob) {

    ExecutorService executorService = Executors.newFixedThreadPool(3);

    ThreadPoolExecutor threadPoolExecutor =
        new ThreadPoolExecutor(
            3, 3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    threadPoolExecutor.prestartAllCoreThreads();
    threadPoolExecutor.prestartCoreThread();

    threadPoolExecutor.allowCoreThreadTimeOut(true);

    startPage();
    List<SysJob> list = jobService.selectJobList(sysJob);
    return getDataTable(list);
  }

  /** 导出定时任务列表 */
  @PreAuthorize("@ss.hasPermi('monitor:job:export')")
  @Log(title = "定时任务", businessType = BusinessType.EXPORT)
  @GetMapping("/export")
  public AjaxResult export(SysJob sysJob) {
    List<SysJob> list = jobService.selectJobList(sysJob);
    ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
    return util.exportExcel(list, "定时任务");
  }

  /** 获取定时任务详细信息 */
  @PreAuthorize("@ss.hasPermi('monitor:job:query')")
  @GetMapping(value = "/{jobId}")
  public AjaxResult getInfo(@PathVariable("jobId") Long jobId) {
    return AjaxResult.success(jobService.selectJobById(jobId));
  }

  /** 新增定时任务 */
  @PreAuthorize("@ss.hasPermi('monitor:job:add')")
  @Log(title = "定时任务", businessType = BusinessType.INSERT)
  @PostMapping
  public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException {
    if (!CronUtils.isValid(job.getCronExpression())) {
      return error("新增任务'" + job.getJobName() + "'失败，Cron表达式不正确");
    } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) {
      return error("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'rmi://'调用");
    } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP)) {
      return error("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'ldap://'调用");
    } else if (StringUtils.containsAnyIgnoreCase(
        job.getInvokeTarget(), new String[] {Constants.HTTP, Constants.HTTPS})) {
      return error("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'http(s)//'调用");
    }
    job.setCreateBy(getUsername());
    return toAjax(jobService.insertJob(job));
  }

  /** 修改定时任务 */
  @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
  @Log(title = "定时任务", businessType = BusinessType.UPDATE)
  @PutMapping
  public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException {
    if (!CronUtils.isValid(job.getCronExpression())) {
      return error("修改任务'" + job.getJobName() + "'失败，Cron表达式不正确");
    } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) {
      return error("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'rmi://'调用");
    } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP)) {
      return error("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'ldap://'调用");
    } else if (StringUtils.containsAnyIgnoreCase(
        job.getInvokeTarget(), new String[] {Constants.HTTP, Constants.HTTPS})) {
      return error("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'http(s)//'调用");
    }
    job.setUpdateBy(getUsername());
    return toAjax(jobService.updateJob(job));
  }

  /** 定时任务状态修改 */
  @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
  @Log(title = "定时任务", businessType = BusinessType.UPDATE)
  @PutMapping("/changeStatus")
  public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException {
    SysJob newJob = jobService.selectJobById(job.getJobId());
    newJob.setStatus(job.getStatus());
    return toAjax(jobService.changeStatus(newJob));
  }

  /** 定时任务立即执行一次 */
  @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
  @Log(title = "定时任务", businessType = BusinessType.UPDATE)
  @PutMapping("/run")
  public AjaxResult run(@RequestBody SysJob job) throws SchedulerException {
    jobService.run(job);
    return AjaxResult.success();
  }

  /** 删除定时任务 */
  @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
  @Log(title = "定时任务", businessType = BusinessType.DELETE)
  @DeleteMapping("/{jobIds}")
  public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException {
    jobService.deleteJobByIds(jobIds);
    return AjaxResult.success();
  }
}
